package com.aabte.lota.auth.auth.token;

import com.aabte.commons.rest.enums.StandardErrorCode;
import com.aabte.commons.rest.exception.ApiException;
import com.aabte.lota.auth.auth.bean.constant.LoginConstants;
import com.aabte.lota.auth.auth.shiro.JwtToken;
import com.aabte.lota.auth.auth.token.exception.TokenException;
import com.aabte.lota.auth.auth.token.payload.TokenPayloadDTO;
import com.aabte.lota.auth.common.util.ServletUtils;
import io.jsonwebtoken.Claims;
import java.io.IOException;
import java.time.Instant;
import javax.annotation.Resource;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;

/**
 * @author Daniel
 * @version 1.0
 * @date 2020/4/6
 */
public class JWTTokenRefreshFilter implements Filter {

  @Resource private JWTProperites jwtProperites;

  @Resource private JWTTokenUtils jwtTokenUtils;

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {

    boolean isRefresh = false;
    TokenPayloadDTO tokenPayload = null;
    Subject subject = SecurityUtils.getSubject();
    if (subject.isAuthenticated()) {
      Object principal = subject.getPrincipal();
      if (principal instanceof JwtToken) {
        JwtToken jwtToken = (JwtToken) principal;
        String token = jwtToken.getToken();
        long issuedAt;
        try {
          issuedAt = jwtTokenUtils.parseTokenIssuedAt(token);
          tokenPayload = jwtTokenUtils.parseToken(token);
        } catch (TokenException e) {
          throw new ApiException(
              StandardErrorCode.Unauthorized.getStatus(),
              StandardErrorCode.Unauthorized.getCode(),
              e.getMessage());
        }
        isRefresh =
            Instant.now().getEpochSecond() - issuedAt / 1000 > jwtProperites.getRefreshPeriod();
      }
    }

    if (isRefresh && null != tokenPayload) {
      Claims claims = jwtTokenUtils.createClaims(tokenPayload);
      String token = jwtTokenUtils.generateToken(claims);
      ServletUtils.setResponseHeader(LoginConstants.HEADER_NAME_AUTHORIZATION, token);
    }

    // 放到后面，否则不生效
    chain.doFilter(request, response);
  }
}
